package com.file.parser.socialsecurity;

import com.file.bo.ResponseData;
import com.file.bo.socialsecurity.ShandongIndividualRecordSheet;
import com.file.bo.socialsecurity.ShandongInsuranceParticipation;
import com.file.constant.ErrorCode;
import com.file.parser.BasePdfParser;
import com.file.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ShandongSocialSecurityPdfParser extends BasePdfParser {

    public ResponseData<String> parseShandongSocialSecurityPdfToJson(String daId, String filePath) {
        log.info("parseShandongSocialSecurityPdfToJson started, daId:{}", daId);
        String json = null;

        try {
            if (filePath.contains("cbzm")) {
                ShandongInsuranceParticipation henanInsuranceParticipation = parseShandongInsuranceParticipation(filePath);
                json = JsonUtils.convertObjectToJson(henanInsuranceParticipation);
            } else if (filePath.contains("qyd")) {//NOSONAR
                ShandongIndividualRecordSheet hananIndividualRecordSheet = parseShandongIndividualRecordSheet(filePath);
                json = JsonUtils.convertObjectToJson(hananIndividualRecordSheet);//NOSONAR
            } else {
                log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseShandongSocialSecurityPdfToJson failed, new type not supported");
                return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
            }
        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseShandongSocialSecurityPdfToJson failed", e);
            return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseShandongSocialSecurityPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private ShandongInsuranceParticipation parseShandongInsuranceParticipation(String filePath) {
        ShandongInsuranceParticipation shandongInsuranceParticipation = parseShandongInsuranceParticipationHeader(filePath);
        List<List<String>> rowList = parseFileToRowList(filePath);
        for (List<String> cellList : rowList) {
//            System.out.println(cellList);   //NOSONAR
        }

        parseListToBO(rowList, shandongInsuranceParticipation);

        return shandongInsuranceParticipation;
    }

    private void parseListToBO(List<List<String>> rowList, ShandongInsuranceParticipation shandongInsuranceParticipation) {
        List<ShandongInsuranceParticipation.InsuranceDetails> insuranceDetailsList = new ArrayList<>();
        shandongInsuranceParticipation.setInsuranceDetailsList(insuranceDetailsList);
        String sectionName = "";

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);
            if (StringUtils.equals(cellList.get(0), "姓名")) {
                sectionName = "姓名";
            } else if (StringUtils.contains(cellList.get(0), "当前参保单位:")) {
                sectionName = "当前参保单位";
            } else if (StringUtils.contains(cellList.get(0), "参保状态:")) {
                sectionName = "参保状态";
            } else if (StringUtils.equals(cellList.get(0), "当前参保单位") && StringUtils.equals(cellList.get(2), "参保状态")) {
                sectionName = "当前参保单位-参保状态";
            } else if (StringUtils.equals(cellList.get(0), "当前参保单位") && StringUtils.isBlank(cellList.get(2))) {
                sectionName = "当前参保单位-";
            } else if (StringUtils.equals(cellList.get(0), "参保情况") && StringUtils.equals(cellList.get(2), "参保状态")) {
                sectionName = "参保情况-参保状态";
            } else if (StringUtils.equalsAny(cellList.get(0), "参保情况:", "险种")) {
                sectionName = "参保情况";
                continue;
            }

            switch (sectionName) {//NOSONAR
                case "姓名":
                    if (StringUtils.isBlank(shandongInsuranceParticipation.getName())) {
                        shandongInsuranceParticipation.setName(cellList.get(1));
                    }
                    if (StringUtils.isBlank(shandongInsuranceParticipation.getIdNo())) {
                        shandongInsuranceParticipation.setIdNo(cellList.get(3));
                    }
                    break;
                case "当前参保单位-参保状态":
                    if (StringUtils.isBlank(shandongInsuranceParticipation.getCurrentInsuredUnit())) {
                        shandongInsuranceParticipation.setCurrentInsuredUnit(cellList.get(1));
                    }
                    if (StringUtils.isBlank(shandongInsuranceParticipation.getInsuranceStatus())) {
                        shandongInsuranceParticipation.setInsuranceStatus(cellList.get(3));
                    }
                    break;
                case "参保情况-参保状态":
                    if (StringUtils.isBlank(shandongInsuranceParticipation.getInsuranceStatus())) {
                        shandongInsuranceParticipation.setInsuranceStatus(cellList.get(3));
                    }
                    break;
                case "当前参保单位":
                    if (StringUtils.isBlank(shandongInsuranceParticipation.getCurrentInsuredUnit())) {
                        String cellText = cellList.get(0);
                        if (StringUtils.contains(cellText, "当前参保单位: ")) {
                            cellText = cellText.substring(cellText.indexOf("当前参保单位: ") + 7).trim();
                        }
                        shandongInsuranceParticipation.setCurrentInsuredUnit(cellText);
                    }
                    break;
                case "参保状态":
                    if (StringUtils.isBlank(shandongInsuranceParticipation.getInsuranceStatus())) {
                        String cellText = cellList.get(0);
                        if (StringUtils.contains(cellText, "参保状态: ")) {
                            cellText = cellText.substring(cellText.indexOf("参保状态: ") + 5).trim();
                        }
                        shandongInsuranceParticipation.setInsuranceStatus(cellText);
                    }
                    break;
                case "当前参保单位-":
                    if (StringUtils.isBlank(shandongInsuranceParticipation.getCurrentInsuredUnit())) {
                        shandongInsuranceParticipation.setCurrentInsuredUnit(cellList.get(1));
                    }
                    break;
                case "参保情况":
                    ShandongInsuranceParticipation.InsuranceDetails insuranceDetails = new ShandongInsuranceParticipation.InsuranceDetails();
                    insuranceDetails.setInsuranceType(cellList.get(0));
                    if (StringUtils.isNotEmpty(cellList.get(2))) {
                        insuranceDetails.setInsuranceStartAndEndTime(cellList.get(1));
                        insuranceDetails.setAccumulatedPaymentMonths(cellList.get(2));
                    } else {
                        insuranceDetails.setInsuranceStartAndEndTime(cellList.get(1).substring(0, cellList.get(1).lastIndexOf("-") + 7));
                        insuranceDetails.setAccumulatedPaymentMonths(cellList.get(1).substring(cellList.get(1).lastIndexOf("-")).substring(7));
                    }

                    insuranceDetailsList.add(insuranceDetails);
                    break;
            }
        }
    }

    private List<List<String>> parseFileToRowList(String filePath) {
        // 1. 读取文件
        File pdf = new File(filePath);

        //页面所有table的记录，每一个元素代表下面一条记录cellList
        List<List<String>> rowList = new ArrayList<>();

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {
            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            SpreadsheetDetectionAlgorithm detectionAlgorithm = new SpreadsheetDetectionAlgorithm();
            Map<Integer, List<Rectangle>> pageNumber2RectangleListMap = new HashMap<>();//key为页的序号， value为对应的Rectangle的list

            // 4. 获取每页的PageIterator
            PageIterator pageIterator = objectExtractor.extract();

            // 5. 解析每页的Rectangle
            // 如果单页pdf中有多个Rectangle，则解析出来的List<Rectangle>会有多个对象
            while (pageIterator.hasNext()) {
                Page page = pageIterator.next();
                List<Rectangle> rectangleList = detectionAlgorithm.detect(page);
                if (rectangleList.size() > 0) {
                    pageNumber2RectangleListMap.put(page.getPageNumber(), rectangleList);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm extractionAlgorithm = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : pageNumber2RectangleListMap.entrySet()) {
                Page page = objectExtractor.extract(entry.getKey());
                Rectangle rectangle = null;

                List<Rectangle> rectangleList = entry.getValue();
                for (Rectangle r : rectangleList) {
                    double rectangleHeight = r.getHeight();
                    if (Double.compare(rectangleHeight, 0) > 0) {
                        rectangle = r;
                        break;
                    }
                }
                if (rectangle == null) {
                    throw new RuntimeException("rectangle is null.");
                }

                if (entry.getKey() > 1) {
                    rectangle.setTop(rectangle.getTop());
                }
                rectangle.setBottom(rectangle.getBottom() + 300);
                Page area = page.getArea(rectangle);

                // 如果每页有多个表格，解析每一个table
                List<Table> tableList = extractionAlgorithm.extract(area);
                for (Table table : tableList) {
                    for (int i = 0; i < table.getRowCount(); i++) {
                        List<String> cellList = new ArrayList<>();//一条记录，每个单元格占一个元素
                        for (int j = 0; j < table.getColCount(); j++) {
                            cellList.add(table.getCell(i, j).getText(false));
                        }
                        rowList.add(cellList);
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return rowList;
    }

    private ShandongInsuranceParticipation parseShandongInsuranceParticipationHeader(String filePath) {
        ShandongInsuranceParticipation shandongInsuranceParticipation = new ShandongInsuranceParticipation();
        String pdfText = getPdfTextByStripper2(filePath)
                .replace(System.getProperty("line.separator", "\n"), StringUtils.EMPTY);
//        System.out.println(pdfText);

        String proofNumber = "";
        if (pdfText.indexOf("校验码:") > 0) {  //NOSONAR
            proofNumber = pdfText.substring(pdfText.indexOf("证明编号：") + 5, pdfText.indexOf("校验码:")).trim();
        } else {
            proofNumber = pdfText.substring(pdfText.indexOf("证明编号：") + 5, pdfText.indexOf("姓名")).trim();
        }

        String notes = pdfText.substring(pdfText.indexOf("备注：") + 3, pdfText.indexOf("社会保险经办机构（章）")).trim();

        String printTime = "";
        if (pdfText.indexOf("说明：") > 0) {   //NOSONAR
            printTime = pdfText.substring(pdfText.indexOf("社会保险经办机构（章）") + 11, pdfText.indexOf("说明：")).trim();
        } else {
            printTime = pdfText.substring(pdfText.indexOf("社会保险经办机构（章）") + 11).trim();
        }
        if (!StringUtils.endsWith(printTime, "日")) {
            printTime = printTime.substring(0, printTime.indexOf("日") + 1);
        }

        shandongInsuranceParticipation.setProofNumber(proofNumber);
        shandongInsuranceParticipation.setNotes(notes);
        shandongInsuranceParticipation.setPrintTime(printTime);

        return shandongInsuranceParticipation;
    }

    private ShandongIndividualRecordSheet parseShandongIndividualRecordSheetHeader(String filePath) {
        ShandongIndividualRecordSheet shandongIndividualRecordSheet = new ShandongIndividualRecordSheet();
        String pdfText = getPdfTextByStripper2(filePath)
                .replace(System.getProperty("line.separator", "\n"), StringUtils.EMPTY);
//        System.out.println(pdfText);
        String recordPeriod = pdfText.substring(0, pdfText.indexOf("年度")).trim();
        recordPeriod = recordPeriod + "年1月至" + recordPeriod + "年12月";
        String tips = pdfText.substring(pdfText.indexOf("温馨提示：") + 5).trim();
        String printTime = pdfText.substring(pdfText.indexOf("打印时间：") + 5, pdfText.indexOf("打印时间：") + 21).trim();
        shandongIndividualRecordSheet.setRecordPeriod(recordPeriod);
        shandongIndividualRecordSheet.setTips(tips);
        shandongIndividualRecordSheet.setPrintTime(printTime.replaceAll(StringUtils.SPACE, ""));
        return shandongIndividualRecordSheet;
    }

    private ShandongIndividualRecordSheet parseShandongIndividualRecordSheet(String filePath) { //NOSONAR
        ShandongIndividualRecordSheet shandongIndividualRecordSheet = parseShandongIndividualRecordSheetHeader(filePath);
        List<List<String>> rowList = parseFileToRowList(filePath);
//        for (List<String> cellList : rowList) {
//            System.out.println(cellList);
//        }
        parseListToBO(rowList, shandongIndividualRecordSheet);

        return shandongIndividualRecordSheet;
    }

    private void parseListToBO(List<List<String>> rowList, ShandongIndividualRecordSheet shandongIndividualRecordSheet) {
        ShandongIndividualRecordSheet.PaymentStatus paymentStatus = new ShandongIndividualRecordSheet.PaymentStatus();
        shandongIndividualRecordSheet.setPaymentStatus(paymentStatus);

        String sectionName = "";

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);
            if (StringUtils.equals(cellList.get(0), "姓名")) {
                sectionName = "姓名";
            } else if (StringUtils.equals(cellList.get(0), "本人首次缴费年月")) {
                sectionName = "本人首次缴费年月";
                continue;
            } else if (StringUtils.contains(cellList.get(0), "缴费情况") || StringUtils.equalsAny(cellList.get(0), "个人缴费基数", "养老")) {
                sectionName = "缴费情况";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "养老保险截至本年末实际缴费月数")) {
                sectionName = "养老保险截至本年末实际缴费月数";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "养老金领取情况(离退休)")) {
                break;
            }

            switch (sectionName) {//NOSONAR
                case "姓名":
                    shandongIndividualRecordSheet.setName(cellList.get(1));
                    shandongIndividualRecordSheet.setUnitName(cellList.get(3));
                    shandongIndividualRecordSheet.setSocialSecurityNumber(cellList.get(5));
                    break;
                case "本人首次缴费年月":
                    ShandongIndividualRecordSheet.MyFirstPaymentDate myFirstPaymentDate = new ShandongIndividualRecordSheet.MyFirstPaymentDate();
                    myFirstPaymentDate.setEndowmentInsurance(cellList.get(1));
                    myFirstPaymentDate.setEmploymentInjuryInsurance(cellList.get(2));
                    myFirstPaymentDate.setUnemploymentInsurance(cellList.get(3));
                    myFirstPaymentDate.setResidentPensionInsurance(cellList.get(4));
                    shandongIndividualRecordSheet.setMyFirstPaymentDate(myFirstPaymentDate);
                    break;
                case "缴费情况":
                    ShandongIndividualRecordSheet.IndividualPaymentBase individualPaymentBase = new ShandongIndividualRecordSheet.IndividualPaymentBase();
                    individualPaymentBase.setEndowment(cellList.get(0));
                    individualPaymentBase.setEmploymentInjury(cellList.get(1));
                    individualPaymentBase.setUnemployment(cellList.get(2));
                    paymentStatus.setIndividualPaymentBase(individualPaymentBase);

                    ShandongIndividualRecordSheet.PensionPaymentInformation pensionPaymentInformation = new ShandongIndividualRecordSheet.PensionPaymentInformation();
                    pensionPaymentInformation.setUnitPaymentAmount(cellList.get(3));
                    pensionPaymentInformation.setIndividualPaymentAmount(cellList.get(4));
                    paymentStatus.setPensionPaymentInformation(pensionPaymentInformation);

                    ShandongIndividualRecordSheet.UnemploymentPaymentInformation unemploymentPaymentInformation = new ShandongIndividualRecordSheet.UnemploymentPaymentInformation();
                    unemploymentPaymentInformation.setUnitPaymentAmount(cellList.get(5));
                    unemploymentPaymentInformation.setIndividualPaymentAmount(cellList.get(6));
                    paymentStatus.setUnemploymentPaymentInformation(unemploymentPaymentInformation);

                    ShandongIndividualRecordSheet.EmploymentInjuryPaymentInformation employmentInjuryPaymentInformation = new ShandongIndividualRecordSheet.EmploymentInjuryPaymentInformation();
                    employmentInjuryPaymentInformation.setUnitPaymentAmount(cellList.get(7));
                    paymentStatus.setEmploymentInjuryPaymentInformation(employmentInjuryPaymentInformation);

                    if (cellList.size() > 8) {
                        ShandongIndividualRecordSheet.ResidentPensionInsurance residentPensionInsurance = new ShandongIndividualRecordSheet.ResidentPensionInsurance();
                        residentPensionInsurance.setAnnualPaymentAmount(cellList.get(8));
                        paymentStatus.setResidentPensionInsurance(residentPensionInsurance);
                    }
                    break;
                case "养老保险截至本年末实际缴费月数":
                    if (StringUtils.contains(cellList.get(2), ".")) {
                        paymentStatus.setActualPaymentMonthsForPensionInsuranceByEndOfThisYear(cellList.get(0));
                        paymentStatus.setActualPaymentYearsForResidentPensionInsuranceByEndOfThisYear(cellList.get(1));
                        paymentStatus.setAccumulatedBalanceOfPersonalAccountForPensionInsuranceByEndOfThisYear(cellList.get(2));
                    } else {
                        paymentStatus.setActualPaymentMonthsForPensionInsuranceByEndOfThisYear(cellList.get(0));
                        paymentStatus.setAccumulatedBalanceOfPersonalAccountForPensionInsuranceByEndOfThisYear(cellList.get(1));
                    }

                    break;
            }
        }
    }

//    public static void main(String[] args) {
//        String filePath = "D:\\data\\file\\socialsecurity\\山东\\zd4akdkf1731961122844020736_5211b67b0a3eef0d361bbfdec2ef5179_app-gjzwfw-dzsb_origins\\app-gjzwfw-dzsb_qyd.pdf";
//        ShandongSocialSecurityPdfParser shandongSocialSecurityPdfParser = new ShandongSocialSecurityPdfParser();
//        String json = shandongSocialSecurityPdfParser.parseShandongSocialSecurityPdfToJson("", filePath).getData();
//        System.out.println(json);

//        String filePath = "D:\\data\\file\\socialsecurity\\山东\\zd4akdkf1731961122844020736_5211b67b0a3eef0d361bbfdec2ef5179_app-gjzwfw-dzsb_origins\\app-gjzwfw-dzsb_qyd.pdf";
//        ShandongSocialSecurityPdfParser shandongSocialSecurityPdfParser = new ShandongSocialSecurityPdfParser();
//        String json = shandongSocialSecurityPdfParser.parseShandongSocialSecurityPdfToJson("", filePath).getData();
//        System.out.println(json);
//    }

}
